﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FDSimpleModelGenerator.Common;
using FDSimpleModelGenerator.Common.Enums;
using FDSimpleModelGenerator.Entities;
using FDSimpleModelGenerator.Entities.Enums;
using FDSimpleModelGenerator.IServices;
using Microsoft.Data.Sqlite;

namespace FDSimpleModelGenerator.Services.Sqlite
{
    /// <summary>
    /// 生成Sqlite模型
    /// </summary>
    public class GenerateModelSqliteService : IGenerateModelService
    {
        private readonly IExceptionThrowFactory _exceptionThrowFactory;
        private readonly IDbConfigResolver _configResolver;
        private readonly IDbAccessor _dbAccessor;
        private readonly IModelGenerateEngine _modelGenerateEngine;

        public GenerateModelSqliteService(IExceptionThrowFactory exceptionThrowFactory, IDbAccessor dbAccessor,
            IModelGenerateEngine modelGenerateEngine, IEnumerable<IDbConfigResolver> dbConfigResolvers)
        {
            _modelGenerateEngine = modelGenerateEngine;
            _dbAccessor = dbAccessor;
            _exceptionThrowFactory = exceptionThrowFactory;
            _configResolver = dbConfigResolvers.First(r => r.DbType == DbType);
        }

        public DbType DbType => DbType.Sqlite;

        public async Task<string> GenerateAsync(DbConfig dbConfig, string tableName, string templateContent,
            string namespaceName = "FDSimpleModelGenerator", LanguageDataType languageDataType = LanguageDataType.CSharp, bool propertyFirstCharLower = false)
        {
            return await Task.Run(() =>
                Generate(dbConfig, tableName, templateContent, namespaceName, languageDataType, propertyFirstCharLower));
        }

        /// <summary>
        /// 生成模型
        /// </summary>
        /// <param name="dbConfig"></param>
        /// <param name="tableName"></param>
        /// <param name="templateContent"></param>
        /// <param name="namespaceName">命名空间</param>
        /// <param name="propertyFirstCharLower"></param>
        /// <param name="languageDataType"></param>
        /// <returns></returns>
        public string Generate(DbConfig dbConfig, string tableName, string templateContent, string namespaceName, LanguageDataType languageDataType, bool propertyFirstCharLower)
        {
            var connString = _configResolver.GetConnectionString(dbConfig);
            _dbAccessor.Init(() => new SqliteConnection(connString));
            var sql = $"PRAGMA table_info({tableName})";

            //var tableInfo = _dbAccessor.Get<NameValue<string>>(sqlTable, new { tableName, dbName = dbConfig.Database });
            var columns = _dbAccessor.GetList<SqliteColumn>(sql, new { tableName, dbName = dbConfig.Database });

            var tableColumns = columns.Select(c => new TableColumn
            {
                Name = c.Name,
                ColumnType = c.Type,
                Description = c.Name,
                Key = c.Pk
            }).ToList();

            var tableParam = new TableInfo
            {
                Description = tableName,
                Name = tableName,
                TableColumns = tableColumns
            };
            return _modelGenerateEngine.Generate(tableParam, templateContent, namespaceName, languageDataType, propertyFirstCharLower);
        }
    }
}
